#include "modbus.h"

#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#include <cstdio>
#include <cerrno>
modbus::modbus(const char *address, int port)
{
  
    FD_ZERO(&m_redset);
}

modbus::~modbus()
{
    modbus_mapping_free(m_mapping); // free mapping space
    modbus_close(m_ctx);
    modbus_free(m_ctx);
}
void modbus::setMapping(int nb_bits, int nb_input_bits,
                        int nb_registers, int nb_input_registers)
{
    m_mapping = modbus_mapping_new(nb_bits, nb_input_bits, nb_registers, nb_input_registers);
    // create new mapping space
}

void modbus::Listen()
{
    if(m_type == ConnectType::ModbusTcp)
        m_listen_fd = modbus_tcp_listen(m_ctx, 5); // open socket listen
    // modbus_tcp_accept(m_ctx, &ret);
}

void modbus::setConnectType(ConnectType types)
{
    m_type = types;
    if(m_type == ConnectType::ModbusTcp)
        m_ctx = modbus_new_tcp(NULL, 5002); // create socket new tcp address
}
int modbus::ModbusTcpAccept(int psock,fd_set *rset)
{
    int src;
    timeval tv;
    timeval *ptv;
    fd_set temp_set = *rset;
    uint32_t sec = 2;
    uint32_t usec =5000;

    modbus_get_indication_timeout(m_ctx,&sec,&usec);
    tv.tv_sec = sec;
    tv.tv_usec = usec;
    ptv = &tv;
    while ((src =select(psock+1,&temp_set,NULL,NULL,ptv))==-1)
    {
        FD_ZERO(&temp_set);
        temp_set = *rset;
    }
    *rset = temp_set;
    return src;
}
/**
 * @brief open loop
 *
 */
void modbus::loop()
{
    uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH];
    int newfd;
    FD_SET(m_listen_fd, &m_redset); // set select

    int fdmax = m_listen_fd + 1;
    for (;;)
    {
        fd_set temp = m_redset;
        if (select(fdmax + 1, &temp, NULL, NULL, NULL) == -1)
        {
            perror("select error");
            return;
        }
        else 
        {
            ModbusTcpAccept(m_listen_fd,&temp);
            for (int i = 0; i < fdmax; i++)
            {
               if(FD_ISSET(i,&temp)) continue;
               modbus_set_socket(m_ctx,i);
               int len = modbus_receive(m_ctx,query);
            }
            
        }
          
    }
    printf("Quit the loop: %s\n", modbus_strerror(errno));
}
void close_fd(int fd)
{
    close(fd);
}